/* NicEdit - Micro Inline WYSIWYG
 * Copyright 2007-2008 Brian Kirchoff
 *
 * NicEdit is distributed under the terms of the MIT license
 * For more information visit http://nicedit.com/
 * Do not remove this copyright message
 */
var bkExtend = function(){
  var args = arguments;
  if (args.length == 1) args = [this, args[0]];
  for (var prop in args[1]) args[0][prop] = args[1][prop];
  return args[0];
};
function bkClass() { }
bkClass.prototype.construct = function() {};
bkClass.extend = function(def) {
  var classDef = function() {
    if (arguments[0] !== bkClass) { return this.construct.apply(this, arguments); }
  };
  var proto = new this(bkClass);
  bkExtend(proto,def);
  classDef.prototype = proto;
  classDef.extend = this.extend;
  return classDef;
};

var bkElement = bkClass.extend({
  construct : function(elm,d) {
    if(typeof(elm) == "string") {
      elm = (d || document).createElement(elm);
    }
    elm = $BK(elm);
    return elm;
  },

  appendTo : function(elm) {
    elm.appendChild(this);
    return this;
  },

  appendBefore : function(elm) {
    elm.parentNode.insertBefore(this,elm);
    return this;
  },

  addEvent : function(type, fn) {
    bkLib.addEvent(this,type,fn);
    return this;
  },

  setContent : function(c) {
    this.innerHTML = c;
    return this;
  },

  pos : function() {
    var curleft = curtop = 0;
    var o = obj = this;
    if (obj.offsetParent) {
      do {
        curleft += obj.offsetLeft;
        curtop += obj.offsetTop;
      } while (obj = obj.offsetParent);
    }
    var b = (!window.opera) ? parseInt(this.getStyle('border-width') || this.style.border) || 0 : 0;
    return [curleft+b,curtop+b+this.offsetHeight];
  },

  noSelect : function() {
    bkLib.noSelect(this);
    return this;
  },

  parentTag : function(t) {
    var elm = this;
    do {
      if(elm && elm.nodeName && elm.nodeName.toUpperCase() == t) {
        return elm;
      }
      elm = elm.parentNode;
    } while(elm);
    return false;
  },

  hasClass : function(cls) {
    return this.className.match(new RegExp('(\\s|^)nicEdit-'+cls+'(\\s|$)'));
  },

  addClass : function(cls) {
    if (!this.hasClass(cls)) { this.className += " nicEdit-"+cls };
    return this;
  },

  removeClass : function(cls) {
    if (this.hasClass(cls)) {
      this.className = this.className.replace(new RegExp('(\\s|^)nicEdit-'+cls+'(\\s|$)'),' ');
    }
    return this;
  },

  setStyle : function(st) {
    var elmStyle = this.style;
    for(var itm in st) {
      switch(itm) {
        case 'float':
          elmStyle['cssFloat'] = elmStyle['styleFloat'] = st[itm];
          break;
        case 'opacity':
          elmStyle.opacity = st[itm];
          elmStyle.filter = "alpha(opacity=" + Math.round(st[itm]*100) + ")";
          break;
        case 'className':
          this.className = st[itm];
          break;
        default:
          //if(document.compatMode || itm != "cursor") { // Nasty Workaround for IE 5.5
          elmStyle[itm] = st[itm];
        //}
      }
    }
    return this;
  },

  getStyle : function( cssRule, d ) {
    var doc = (!d) ? document.defaultView : d;
    if(this.nodeType == 1)
      return (doc && doc.getComputedStyle) ? doc.getComputedStyle( this, null ).getPropertyValue(cssRule) : this.currentStyle[ bkLib.camelize(cssRule) ];
  },

  remove : function() {
    this.parentNode.removeChild(this);
    return this;
  },

  setAttributes : function(at) {
    for(var itm in at) {
      this[itm] = at[itm];
    }
    return this;
  }
});

var bkLib = {
  isMSIE : (navigator.appVersion.indexOf("MSIE") != -1),

  addEvent : function(obj, type, fn) {
    (obj.addEventListener) ? obj.addEventListener( type, fn, false ) : obj.attachEvent("on"+type, fn);
  },

  toArray : function(iterable) {
    var length = iterable.length, results = new Array(length);
    while (length--) { results[length] = iterable[length] };
    return results;
  },

  noSelect : function(element) {
    if(element.setAttribute && element.nodeName.toLowerCase() != 'input' && element.nodeName.toLowerCase() != 'textarea') {
      element.setAttribute('unselectable','on');
    }
    for(var i=0;i<element.childNodes.length;i++) {
      bkLib.noSelect(element.childNodes[i]);
    }
  },
  camelize : function(s) {
    return s.replace(/\-(.)/g, function(m, l){return l.toUpperCase()});
  },
  inArray : function(arr,item) {
    return (bkLib.search(arr,item) != null);
  },
  search : function(arr,itm) {
    for(var i=0; i < arr.length; i++) {
      if(arr[i] == itm)
        return i;
    }
    return null;
  },
  cancelEvent : function(e) {
    e = e || window.event;
    if(e.preventDefault && e.stopPropagation) {
      e.preventDefault();
      e.stopPropagation();
    }
    return false;
  },
  domLoad : [],
  domLoaded : function() {
    if (arguments.callee.done) return;
    arguments.callee.done = true;
    for (i = 0;i < bkLib.domLoad.length;i++) bkLib.domLoad[i]();
  },
  onDomLoaded : function(fireThis) {
    this.domLoad.push(fireThis);
    if (document.addEventListener) {
      document.addEventListener("DOMContentLoaded", bkLib.domLoaded, null);
    } else if(bkLib.isMSIE) {
      document.write("<style>.nicEdit-main p { margin: 0; }</style><scr"+"ipt id=__ie_onload defer " + ((location.protocol == "https:") ? "src='javascript:void(0)'" : "src=//0") + "><\/scr"+"ipt>");
      $BK("__ie_onload").onreadystatechange = function() {
        if (this.readyState == "complete"){bkLib.domLoaded();}
      };
    }
    window.onload = bkLib.domLoaded;
  }
};

function $BK(elm) {
  if(typeof(elm) == "string") {
    elm = document.getElementById(elm);
  }
  return (elm && !elm.appendTo) ? bkExtend(elm,bkElement.prototype) : elm;
}

var bkEvent = {
  addEvent : function(evType, evFunc) {
    if(evFunc) {
      this.eventList = this.eventList || {};
      this.eventList[evType] = this.eventList[evType] || [];
      this.eventList[evType].push(evFunc);
    }
    return this;
  },
  fireEvent : function() {
    var args = bkLib.toArray(arguments), evType = args.shift();
    if(this.eventList && this.eventList[evType]) {
      for(var i=0;i<this.eventList[evType].length;i++) {
        this.eventList[evType][i].apply(this,args);
      }
    }
  }
};

function __(s) {
  return s;
}

Function.prototype.closure = function() {
  var __method = this, args = bkLib.toArray(arguments), obj = args.shift();
  return function() { if(typeof(bkLib) != 'undefined') { return __method.apply(obj,args.concat(bkLib.toArray(arguments))); } };
}

Function.prototype.closureListener = function() {
  var __method = this, args = bkLib.toArray(arguments), object = args.shift();
  return function(e) {
    e = e || window.event;
    if(e.target) { var target = e.target; } else { var target =  e.srcElement };
    return __method.apply(object, [e,target].concat(args) );
  };
}


/* START CONFIG */

var nicEditorConfig = bkClass.extend({
  buttons : {
    'bold' : {name : __('Bold'), command : 'Bold', tags : ['B','STRONG'], css : {'font-weight' : 'bold'}, key : 'b'},
    'italic' : {name : __('Italic'), command : 'Italic', tags : ['EM','I'], css : {'font-style' : 'italic'}, key : 'i'},
    'underline' : {name : __('Underline'), command : 'Underline', tags : ['U'], css : {'text-decoration' : 'underline'}, key : 'u'},
    'left' : {name : __('Left Align'), command : 'justifyleft', noActive : true},
    'center' : {name : __('Center Align'), command : 'justifycenter', noActive : true},
    'right' : {name : __('Right Align'), command : 'justifyright', noActive : true},
    'justify' : {name : __('Justify Align'), command : 'justifyfull', noActive : true},
    'ol' : {name : __('Insert Ordered List'), command : 'insertorderedlist', tags : ['OL']},
    'ul' : 	{name : __('Insert Unordered List'), command : 'insertunorderedlist', tags : ['UL']},
    'subscript' : {name : __('Subscript'), command : 'subscript', tags : ['SUB']},
    'superscript' : {name : __('Superscript'), command : 'superscript', tags : ['SUP']},
    'strikethrough' : {name : __('Strike Through'), command : 'strikeThrough', css : {'text-decoration' : 'line-through'}},
    'removeformat' : {name : __('Remove Formatting'), command : 'removeformat', noActive : true},
    'indent' : {name : __('Indent Text'), command : 'indent', noActive : true},
    'outdent' : {name : __('Remove Indent'), command : 'outdent', noActive : true},
    'hr' : {name : __('Horizontal Rule'), command : 'insertHorizontalRule', noActive : true}
  },
  iconsPath : '/assets/images/nicEdit/nicEditorIcons.gif',
  buttonList : ['save','bold','italic','underline','left','center','right','justify','ol','ul','fontSize','fontFamily','fontFormat','indent','outdent','image','upload','link','unlink','forecolor','bgcolor'],
  iconList : {'fontSize':1,'forecolor':2,'bgcolor':3,'bold':4,'italic':5,'underline':6,'left':7,'center':8,'right':9,'justify':10,'ol':11,'ul':12,'indent':13,'outdent':14,'link':15,'unlink':16 }
});
/* END CONFIG */

var nicEditors = {
  nicPlugins : [],
  editors : [],

  registerPlugin : function(plugin,options) {
    this.nicPlugins.push({p : plugin, o : options});
  },

  allTextAreas : function(nicOptions) {
    var textareas = document.getElementsByTagName("textarea");
    for(var i=0;i<textareas.length;i++) {
      nicEditors.editors.push(new nicEditor(nicOptions).panelInstance(textareas[i]));
    }
    return nicEditors.editors;
  },

  findEditor : function(e) {
    var editors = nicEditors.editors;
    for(var i=0;i<editors.length;i++) {
      if(editors[i].instanceById(e)) {
        return editors[i].instanceById(e);
      }
    }
  }
};


var nicEditor = bkClass.extend({
  construct : function(o) {
    this.options = new nicEditorConfig();
    bkExtend(this.options,o);
    this.nicInstances = new Array();
    this.loadedPlugins = new Array();

    var plugins = nicEditors.nicPlugins;
    for(var i=0;i<plugins.length;i++) {
      this.loadedPlugins.push(new plugins[i].p(this,plugins[i].o));
    }
    nicEditors.editors.push(this);
    bkLib.addEvent(document.body,'mousedown', this.selectCheck.closureListener(this) );
  },

  panelInstance : function(e,o) {
    e = this.checkReplace($BK(e));
    var panelElm = new bkElement('DIV').setStyle({width : (parseInt(e.getStyle('width')) || e.clientWidth)+'px'}).appendBefore(e);
    this.setPanel(panelElm);
    return this.addInstance(e,o);
  },

  checkReplace : function(e) {
    var r = nicEditors.findEditor(e);
    if(r) {
      r.removeInstance(e);
      r.removePanel();
    }
    return e;
  },

  addInstance : function(e,o) {
    e = this.checkReplace($BK(e));
    if( e.contentEditable || !!window.opera ) {
      var newInstance = new nicEditorInstance(e,o,this);
    } else {
      var newInstance = new nicEditorIFrameInstance(e,o,this);
    }
    this.nicInstances.push(newInstance);
    return this;
  },

  removeInstance : function(e) {
    e = $BK(e);
    var instances = this.nicInstances;
    for(var i=0;i<instances.length;i++) {
      if(instances[i].e == e) {
        instances[i].remove();
        this.nicInstances.splice(i,1);
      }
    }
  },

  removePanel : function(e) {
    if(this.nicPanel) {
      this.nicPanel.remove();
      this.nicPanel = null;
    }
  },

  instanceById : function(e) {
    e = $BK(e);
    var instances = this.nicInstances;
    for(var i=0;i<instances.length;i++) {
      if(instances[i].e == e) {
        return instances[i];
      }
    }
  },

  setPanel : function(e) {
    this.nicPanel = new nicEditorPanel($BK(e),this.options,this);
    this.fireEvent('panel',this.nicPanel);
    return this;
  },

  nicCommand : function(cmd,args) {
    if(this.selectedInstance) {
      this.selectedInstance.nicCommand(cmd,args);
    }
  },

  getIcon : function(iconName,options) {
    var icon = this.options.iconList[iconName];
    var file = (options.iconFiles) ? options.iconFiles[iconName] : '';
    return {backgroundImage : "url('"+((icon) ? this.options.iconsPath : file)+"')", backgroundPosition : ((icon) ? ((icon-2)*-28) : 0)+'px 0px'};
  },

  selectCheck : function(e,t) {
    var found = false;
    do{
      if(t.className && t.className.indexOf('nicEdit') != -1) {
        return false;
      }
    } while(t = t.parentNode);
    this.fireEvent('blur',this.selectedInstance,t);
    this.lastSelectedInstance = this.selectedInstance;
    this.selectedInstance = null;
    return false;
  }

});
nicEditor = nicEditor.extend(bkEvent);


var nicEditorInstance = bkClass.extend({
  isSelected : false,

  construct : function(e,options,nicEditor) {
    this.ne = nicEditor;
    this.elm = this.e = e;
    this.options = options || {};

    newX = parseInt(e.getStyle('width')) || e.clientWidth;
    newY = parseInt(e.getStyle('height')) || e.clientHeight;
    this.initialHeight = newY-8;

    var isTextarea = (e.nodeName.toLowerCase() == "textarea");
    if(isTextarea || this.options.hasPanel) {
      var ie7s = (bkLib.isMSIE && !((typeof document.body.style.maxHeight != "undefined") && document.compatMode == "CSS1Compat"))
      var s = {width: newX+'px', border : '1px solid #ccc', borderTop : 0, overflowY : 'auto', overflowX: 'hidden' };
      s[(ie7s) ? 'height' : 'maxHeight'] = (this.ne.options.maxHeight) ? this.ne.options.maxHeight+'px' : null;  // edit by eltriny
      this.editorContain = new bkElement('DIV').setStyle(s).appendBefore(e);
      var editorElm = new bkElement('DIV').setStyle({width : (newX-8)+'px', margin: '4px', minHeight : newY+'px'}).addClass('main').appendTo(this.editorContain);

      e.setStyle({display : 'none'});

      editorElm.innerHTML = e.innerHTML;
      if(isTextarea) {
        editorElm.setContent(e.value);
        this.copyElm = e;
        var f = e.parentTag('FORM');
        if(f) { bkLib.addEvent( f, 'submit', this.saveContent.closure(this)); }
      }
      // editorElm.setStyle((ie7s) ? {height : newY+'px'} : {overflow: 'hidden'});  // edit by eltriny
      this.elm = editorElm;
    }
    this.ne.addEvent('blur',this.blur.closure(this));

    this.init();
    this.blur();
  },

  init : function() {
    this.elm.setAttribute('contentEditable','true');
    if(this.getContent() == "") {
      this.setContent('<br />');
    }
    this.instanceDoc = document.defaultView;
    this.elm.addEvent('mousedown',this.selected.closureListener(this)).addEvent('keypress',this.keyDown.closureListener(this)).addEvent('focus',this.selected.closure(this)).addEvent('blur',this.blur.closure(this)).addEvent('keyup',this.selected.closure(this));
    this.ne.fireEvent('add',this);
  },

  remove : function() {
    this.saveContent();
    if(this.copyElm || this.options.hasPanel) {
      this.editorContain.remove();
      this.e.setStyle({'display' : 'block'});
      this.ne.removePanel();
    }
    this.disable();
    this.ne.fireEvent('remove',this);
  },

  disable : function() {
    this.elm.setAttribute('contentEditable','false');
  },

  getSel : function() {
    return (window.getSelection) ? window.getSelection() : document.selection;
  },

  getRng : function() {
    var s = this.getSel();
    if(!s || s.rangeCount === 0) { return; }
    return (s.rangeCount > 0) ? s.getRangeAt(0) : s.createRange();
  },

  selRng : function(rng,s) {
    if(window.getSelection) {
      s.removeAllRanges();
      s.addRange(rng);
    } else {
      rng.select();
    }
  },

  selElm : function() {
    var r = this.getRng();
    if(!r) { return; }
    if(r.startContainer) {
      var contain = r.startContainer;
      if(r.cloneContents().childNodes.length == 1) {
        for(var i=0;i<contain.childNodes.length;i++) {
          var rng = contain.childNodes[i].ownerDocument.createRange();
          rng.selectNode(contain.childNodes[i]);
          if(r.compareBoundaryPoints(Range.START_TO_START,rng) != 1 &&
            r.compareBoundaryPoints(Range.END_TO_END,rng) != -1) {
            return $BK(contain.childNodes[i]);
          }
        }
      }
      return $BK(contain);
    } else {
      return $BK((this.getSel().type == "Control") ? r.item(0) : r.parentElement());
    }
  },

  saveRng : function() {
    this.savedRange = this.getRng();
    this.savedSel = this.getSel();
  },

  restoreRng : function() {
    if(this.savedRange) {
      this.selRng(this.savedRange,this.savedSel);
    }
  },

  keyDown : function(e,t) {
    if(e.ctrlKey) {
      this.ne.fireEvent('key',this,e);
    }
  },

  selected : function(e,t) {
    if(!t && !(t = this.selElm)) { t = this.selElm(); }
    if(!e.ctrlKey) {
      var selInstance = this.ne.selectedInstance;
      if(selInstance != this) {
        if(selInstance) {
          this.ne.fireEvent('blur',selInstance,t);
        }
        this.ne.selectedInstance = this;
        this.ne.fireEvent('focus',selInstance,t);
      }
      this.ne.fireEvent('selected',selInstance,t);
      this.isFocused = true;
      this.elm.addClass('selected');
    }
    return false;
  },

  blur : function() {
    this.isFocused = false;
    this.elm.removeClass('selected');
  },

  saveContent : function() {
    if(this.copyElm || this.options.hasPanel) {
      this.ne.fireEvent('save',this);
      (this.copyElm) ? this.copyElm.value = this.getContent() : this.e.innerHTML = this.getContent();
    }
  },

  getElm : function() {
    return this.elm;
  },

  getContent : function() {
    this.content = this.getElm().innerHTML;
    this.ne.fireEvent('get',this);
    return this.content;
  },

  setContent : function(e) {
    this.content = e;
    this.ne.fireEvent('set',this);
    this.elm.innerHTML = this.content;
  },

  nicCommand : function(cmd,args) {
    document.execCommand(cmd,false,args);
  }
});

var nicEditorIFrameInstance = nicEditorInstance.extend({
  savedStyles : [],

  init : function() {
    var c = this.elm.innerHTML.replace(/^\s+|\s+$/g, '');
    this.elm.innerHTML = '';
    (!c) ? c = "<br />" : c;
    this.initialContent = c;

    this.elmFrame = new bkElement('iframe').setAttributes({'src' : 'javascript:;', 'frameBorder' : 0, 'allowTransparency' : 'true', 'scrolling' : 'no'}).setStyle({height: '100px', width: '100%'}).addClass('frame').appendTo(this.elm);

    if(this.copyElm) { this.elmFrame.setStyle({width : (this.elm.offsetWidth-4)+'px'}); }

    var styleList = ['font-size','font-family','font-weight','color'];
    for(itm in styleList) {
      this.savedStyles[bkLib.camelize(itm)] = this.elm.getStyle(itm);
    }

    setTimeout(this.initFrame.closure(this),50);
  },

  disable : function() {
    this.elm.innerHTML = this.getContent();
  },

  initFrame : function() {
    var fd = $BK(this.elmFrame.contentWindow.document);
    fd.designMode = "on";
    fd.open();
    var css = this.ne.options.externalCSS;
    fd.write('<html><head>'+((css) ? '<link href="'+css+'" rel="stylesheet" type="text/css" />' : '')+'</head><body id="nicEditContent" style="margin: 0 !important; background-color: transparent !important;">'+this.initialContent+'</body></html>');
    fd.close();
    this.frameDoc = fd;

    this.frameWin = $BK(this.elmFrame.contentWindow);
    this.frameContent = $BK(this.frameWin.document.body).setStyle(this.savedStyles);
    this.instanceDoc = this.frameWin.document.defaultView;

    this.heightUpdate();
    this.frameDoc.addEvent('mousedown', this.selected.closureListener(this)).addEvent('keyup',this.heightUpdate.closureListener(this)).addEvent('keydown',this.keyDown.closureListener(this)).addEvent('keyup',this.selected.closure(this));
    this.ne.fireEvent('add',this);
  },

  getElm : function() {
    return this.frameContent;
  },

  setContent : function(c) {
    this.content = c;
    this.ne.fireEvent('set',this);
    this.frameContent.innerHTML = this.content;
    this.heightUpdate();
  },

  getSel : function() {
    return (this.frameWin) ? this.frameWin.getSelection() : this.frameDoc.selection;
  },

  heightUpdate : function() {
    this.elmFrame.style.height = Math.max(this.frameContent.offsetHeight,this.initialHeight)+'px';
  },

  nicCommand : function(cmd,args) {
    this.frameDoc.execCommand(cmd,false,args);
    setTimeout(this.heightUpdate.closure(this),100);
  }


});
var nicEditorPanel = bkClass.extend({
  construct : function(e,options,nicEditor) {
    this.elm = e;
    this.options = options;
    this.ne = nicEditor;
    this.panelButtons = new Array();
    this.buttonList = bkExtend([],this.ne.options.buttonList);

    this.panelContain = new bkElement('DIV').setStyle({overflow : 'hidden', width : '100%', border : '1px solid #cccccc', backgroundColor : '#efefef'}).addClass('panelContain');
    this.panelElm = new bkElement('DIV').setStyle({margin : '2px', marginTop : '0px', zoom : 1, overflow : 'hidden'}).addClass('panel').appendTo(this.panelContain);
    this.panelContain.appendTo(e);

    var opt = this.ne.options;
    var buttons = opt.buttons;
    for(button in buttons) {
      this.addButton(button,opt,true);
    }
    this.reorder();
    e.noSelect();
  },

  addButton : function(buttonName,options,noOrder) {
    var button = options.buttons[buttonName];
    var type = (button['type']) ? eval('(typeof('+button['type']+') == "undefined") ? null : '+button['type']+';') : nicEditorButton;
    var hasButton = bkLib.inArray(this.buttonList,buttonName);
    if(type && (hasButton || this.ne.options.fullPanel)) {
      this.panelButtons.push(new type(this.panelElm,buttonName,options,this.ne));
      if(!hasButton) {
        this.buttonList.push(buttonName);
      }
    }
  },

  findButton : function(itm) {
    for(var i=0;i<this.panelButtons.length;i++) {
      if(this.panelButtons[i].name == itm)
        return this.panelButtons[i];
    }
  },

  reorder : function() {
    var bl = this.buttonList;
    for(var i=0;i<bl.length;i++) {
      var button = this.findButton(bl[i]);
      if(button) {
        this.panelElm.appendChild(button.margin);
      }
    }
  },

  remove : function() {
    this.elm.remove();
  }
});
var nicEditorButton = bkClass.extend({

  construct : function(e,buttonName,options,nicEditor) {
    this.options = options.buttons[buttonName];
    this.name = buttonName;
    this.ne = nicEditor;
    this.elm = e;

    this.margin = new bkElement('DIV').setStyle({'float' : 'left', marginTop : '2px'}).appendTo(e);
    this.contain = new bkElement('DIV').setStyle({width : '28px', height : '30x'}).addClass('buttonContain').appendTo(this.margin);
    this.border = new bkElement('DIV').setStyle({backgroundColor : '#efefef', border : '1px solid #efefef'}).appendTo(this.contain);
    this.button = new bkElement('DIV').setStyle({width : '28px', height : '29px', overflow : 'hidden', zoom : 1, cursor : 'pointer'}).addClass('button').setStyle(this.ne.getIcon(buttonName,options)).appendTo(this.border);
    this.button.addEvent('mouseover', this.hoverOn.closure(this)).addEvent('mouseout',this.hoverOff.closure(this)).addEvent('mousedown',this.mouseClick.closure(this)).noSelect();

    if(!window.opera) {
      this.button.onmousedown = this.button.onclick = bkLib.cancelEvent;
    }

    nicEditor.addEvent('selected', this.enable.closure(this)).addEvent('blur', this.disable.closure(this)).addEvent('key',this.key.closure(this));

    this.disable();
    this.init();
  },

  init : function() {  },

  hide : function() {
    this.contain.setStyle({display : 'none'});
  },

  updateState : function() {
    if(this.isDisabled) { this.setBg(); }
    else if(this.isHover) { this.setBg('hover'); }
    else if(this.isActive) { this.setBg('active'); }
    else { this.setBg(); }
  },

  setBg : function(state) {
    switch(state) {
      case 'hover':
        var stateStyle = {border : '1px solid #666', backgroundColor : '#ddd'};
        break;
      case 'active':
        var stateStyle = {border : '1px solid #666', backgroundColor : '#ccc'};
        break;
      default:
        var stateStyle = {border : '1px solid #efefef', backgroundColor : '#efefef'};
    }
    this.border.setStyle(stateStyle).addClass('button-'+state);
  },

  checkNodes : function(e) {
    var elm = e;
    do {
      if(this.options.tags && bkLib.inArray(this.options.tags,elm.nodeName)) {
        this.activate();
        return true;
      }
    } while(elm = elm.parentNode && elm.className != "nicEdit");
    elm = $BK(e);
    while(elm.nodeType == 3) {
      elm = $BK(elm.parentNode);
    }
    if(this.options.css) {
      for(itm in this.options.css) {
        if(elm.getStyle(itm,this.ne.selectedInstance.instanceDoc) == this.options.css[itm]) {
          this.activate();
          return true;
        }
      }
    }
    this.deactivate();
    return false;
  },

  activate : function() {
    if(!this.isDisabled) {
      this.isActive = true;
      this.updateState();
      this.ne.fireEvent('buttonActivate',this);
    }
  },

  deactivate : function() {
    this.isActive = false;
    this.updateState();
    if(!this.isDisabled) {
      this.ne.fireEvent('buttonDeactivate',this);
    }
  },

  enable : function(ins,t) {
    this.isDisabled = false;
    this.contain.setStyle({'opacity' : 1}).addClass('buttonEnabled');
    this.updateState();
    this.checkNodes(t);
  },

  disable : function(ins,t) {
    this.isDisabled = true;
    this.contain.setStyle({'opacity' : 0.6}).removeClass('buttonEnabled');
    this.updateState();
  },

  toggleActive : function() {
    (this.isActive) ? this.deactivate() : this.activate();
  },

  hoverOn : function() {
    if(!this.isDisabled) {
      this.isHover = true;
      this.updateState();
      this.ne.fireEvent("buttonOver",this);
    }
  },

  hoverOff : function() {
    this.isHover = false;
    this.updateState();
    this.ne.fireEvent("buttonOut",this);
  },

  mouseClick : function() {
    if(this.options.command) {
      this.ne.nicCommand(this.options.command,this.options.commandArgs);
      if(!this.options.noActive) {
        this.toggleActive();
      }
    }
    this.ne.fireEvent("buttonClick",this);
  },

  key : function(nicInstance,e) {
    if(this.options.key && e.ctrlKey && String.fromCharCode(e.keyCode || e.charCode).toLowerCase() == this.options.key) {
      this.mouseClick();
      if(e.preventDefault) e.preventDefault();
    }
  }

});


var nicPlugin = bkClass.extend({

  construct : function(nicEditor,options) {
    this.options = options;
    this.ne = nicEditor;
    this.ne.addEvent('panel',this.loadPanel.closure(this));

    this.init();
  },

  loadPanel : function(np) {
    var buttons = this.options.buttons;
    for(var button in buttons) {
      np.addButton(button,this.options);
    }
    np.reorder();
  },

  init : function() {  }
});




/* START CONFIG */
var nicPaneOptions = { };
/* END CONFIG */

var nicEditorPane = bkClass.extend({
  construct : function(elm,nicEditor,options,openButton) {
    this.ne = nicEditor;
    this.elm = elm;
    this.pos = elm.pos();

    this.contain = new bkElement('div').setStyle({zIndex : '99999', overflow : 'hidden', position : 'absolute', left : this.pos[0]+'px', top : this.pos[1]+'px'})
    this.pane = new bkElement('div').setStyle({fontSize : '12px', border : '1px solid #ccc', 'overflow': 'hidden', padding : '4px', textAlign: 'left', backgroundColor : '#ffffc9'}).addClass('pane').setStyle(options).appendTo(this.contain);

    if(openButton && !openButton.options.noClose) {
      this.close = new bkElement('div').setStyle({'float' : 'right', height: '16px', width : '16px', cursor : 'pointer'}).setStyle(this.ne.getIcon('close',nicPaneOptions)).addEvent('mousedown',openButton.removePane.closure(this)).appendTo(this.pane);
    }

    this.contain.noSelect().appendTo(document.body);

    this.position();
    this.init();
  },

  init : function() { },

  position : function() {
    if(this.ne.nicPanel) {
      var panelElm = this.ne.nicPanel.elm;
      var panelPos = panelElm.pos();
      var newLeft = panelPos[0]+parseInt(panelElm.getStyle('width'))-(parseInt(this.pane.getStyle('width'))+8);
      if(newLeft < this.pos[0]) {
        // this.contain.setStyle({left : newLeft+'px'});
        this.contain.setStyle({left : ( 30 + parseInt(this.contain.getStyle('left')) - parseInt(this.contain.getStyle('width')) ) + 'px'});
      }
    }
  },

  toggle : function() {
    this.isVisible = !this.isVisible;
    this.contain.setStyle({display : ((this.isVisible) ? 'block' : 'none')});
  },

  remove : function() {
    if(this.contain) {
      this.contain.remove();
      this.contain = null;
    }
  },

  append : function(c) {
    c.appendTo(this.pane);
  },

  setContent : function(c) {
    this.pane.setContent(c);
  }

});



var nicEditorAdvancedButton = nicEditorButton.extend({

  init : function() {
    this.ne.addEvent('selected',this.removePane.closure(this)).addEvent('blur',this.removePane.closure(this));
  },

  mouseClick : function() {
    if(!this.isDisabled) {
      if(this.pane && this.pane.pane) {
        this.removePane();
      } else {
        this.pane = new nicEditorPane(this.contain,this.ne,{width : (this.width || '270px'), backgroundColor : '#fff'},this);
        this.addPane();
        this.ne.selectedInstance.saveRng();
      }
    }
  },

  addForm : function(f,elm) {
    this.form = new bkElement('form').addEvent('submit',this.submit.closureListener(this));
    this.pane.append(this.form);
    this.inputs = {};

    for(itm in f) {
      var field = f[itm];
      var val = '';
      if(elm) {
        val = elm.getAttribute(itm);
      }
      if(!val) {
        val = field['value'] || '';
      }
      var type = f[itm].type;

      if(type == 'title') {
        new bkElement('div').setContent(field.txt).setStyle({fontSize : '14px', fontWeight: 'bold', padding : '0 0 15px 0', margin : '2px 0'}).appendTo(this.form);
      } else {
        var contain = new bkElement('div').setStyle({overflow : 'hidden', clear : 'both', padding :'0 0 8px 0'}).appendTo(this.form);
        if(field.txt) {
          new bkElement('label')
            .setAttributes({'for' : itm})
            .setContent(field.txt)
            .setStyle({
              color:'#4c515a',
              margin : '2px 4px',
              fontSize : '13px',
              width: '55px',
              lineHeight : '20px',
              textAlign : 'left', 'float' : 'left'
            })
            .appendTo(contain);
        }

        switch(type) {
          case 'text':
            this.inputs[itm] = new bkElement('input')
              .setAttributes({id : itm, 'value' : val, 'type' : 'text'})
              .setStyle({
                display: 'block',
                width: '73%',
                padding: '6px 28px 6px 10px',
                color: '#4b515b',
                fontSize: '13px',
                textAlign: 'left',
                border: '1px solid #d0d1d8',
                borderRadius: '2px',
                backgroundColor: '#fff',
                boxSizing: 'border-box'
              })
              .setStyle(field.style)
              .appendTo(contain);
            break;
          case 'select':
            this.inputs[itm] = new bkElement('select')
              .setAttributes({id : itm})
              .setStyle({
                display: 'block',
                height:'30px',
                width: '73%',
                color: '#4b515b',
                fontSize: '13px',
                textAlign: 'left',
                border: '1px solid #d0d1d8',
                borderRadius: '2px',
                backgroundColor: '#fff',
                boxSizing: 'border-box'
              })
              .appendTo(contain);
            for(opt in field.options) {
              var o = new bkElement('option').setAttributes({value : opt, selected : (opt == val) ? 'selected' : ''}).setContent(field.options[opt]).appendTo(this.inputs[itm]);
            }
            break;
          case 'content':
            this.inputs[itm] = new bkElement('textarea').setAttributes({id : itm}).setStyle({border : '1px solid #ccc', 'float' : 'left'}).setStyle(field.style).appendTo(contain);
            this.inputs[itm].value = val;
        }
      }
    }
    new bkElement('input')
      .setAttributes({'type' : 'submit', 'value' : 'OK' })
      .setStyle({
        marginLeft:'52%',
        backgroundColor: '#4c515a',
        border: '1px solid #4c515a',
        color: '#fff',
        position: 'relative',
        display: 'inline-block',
        padding: '5px 8px',
        minWidth: '100px',
        fontSize: '14px',
        textAlign: 'center',
        borderRadius: '3px'
      })
      .appendTo(this.form);
    this.form.onsubmit = bkLib.cancelEvent;
  },

  submit : function() { },

  findElm : function(tag,attr,val) {
    var list = this.ne.selectedInstance.getElm().getElementsByTagName(tag);
    for(var i=0;i<list.length;i++) {
      if(list[i].getAttribute(attr) == val) {
        return $BK(list[i]);
      }
    }
  },

  removePane : function() {
    if(this.pane) {
      this.pane.remove();
      this.pane = null;
      this.ne.selectedInstance.restoreRng();
    }
  }
});


var nicButtonTips = bkClass.extend({
  construct : function(nicEditor) {
    this.ne = nicEditor;
    nicEditor.addEvent('buttonOver',this.show.closure(this)).addEvent('buttonOut',this.hide.closure(this));

  },

  show : function(button) {
    this.timer = setTimeout(this.create.closure(this,button),400);
  },

  create : function(button) {
    this.timer = null;
    if(!this.pane) {
      this.pane = new nicEditorPane(button.button,this.ne,{fontSize : '12px', marginTop : '5px', backgroundColor : '#4e5255', color : '#ffffff'});
      this.pane.setContent(button.options.name);
    }
  },

  hide : function(button) {
    if(this.timer) {
      clearTimeout(this.timer);
    }
    if(this.pane) {
      this.pane = this.pane.remove();
    }
  }
});
nicEditors.registerPlugin(nicButtonTips);



/* START CONFIG */
var nicSelectOptions = {
  buttons : {
    'fontSize' : {name : __('Select Font Size'), type : 'nicEditorFontSizeSelect', command : 'fontsize'},
    'fontFamily' : {name : __('Select Font Family'), type : 'nicEditorFontFamilySelect', command : 'fontname'},
    'fontFormat' : {name : __('Select Font Format'), type : 'nicEditorFontFormatSelect', command : 'formatBlock'}
  }
};
/* END CONFIG */
var nicEditorSelect = bkClass.extend({

  construct : function(e,buttonName,options,nicEditor) {
    this.options = options.buttons[buttonName];
    this.elm = e;
    this.ne = nicEditor;
    this.name = buttonName;
    this.selOptions = new Array();

    this.margin = new bkElement('div').setStyle({'float' : 'left', margin : '4px 1px 0 1px'}).appendTo(this.elm);
    this.contain = new bkElement('div').setStyle({width: '110px', height : '30px', cursor : 'pointer', overflow: 'hidden'}).addClass('selectContain').addEvent('click',this.toggle.closure(this)).appendTo(this.margin);
    this.items = new bkElement('div').setStyle({overflow : 'hidden', zoom : 1, border: '1px solid #ccc', paddingLeft : '3px', backgroundColor : '#fff'}).appendTo(this.contain);
    this.control = new bkElement('div').setStyle({overflow : 'hidden', 'float' : 'right', height: '26px', width : '14px'}).addClass('selectControl').setStyle(this.ne.getIcon('arrow',options)).appendTo(this.items);
    this.txt = new bkElement('div').setStyle({overflow : 'hidden', 'float' : 'left', width : '66px', height : '14px', marginTop : '7px', fontFamily : 'sans-serif', textAlign : 'center', fontSize : '12px'}).addClass('selectTxt').appendTo(this.items);

    if(!window.opera) {
      this.contain.onmousedown = this.control.onmousedown = this.txt.onmousedown = bkLib.cancelEvent;
    }

    this.margin.noSelect();

    this.ne.addEvent('selected', this.enable.closure(this)).addEvent('blur', this.disable.closure(this));

    this.disable();
    this.init();
  },

  disable : function() {
    this.isDisabled = true;
    this.close();
    this.contain.setStyle({opacity : 0.6});
  },

  enable : function(t) {
    this.isDisabled = false;
    this.close();
    this.contain.setStyle({opacity : 1});
  },

  setDisplay : function(txt) {
    this.txt.setContent(txt);
  },

  toggle : function() {
    if(!this.isDisabled) {
      (this.pane) ? this.close() : this.open();
    }
  },

  open : function() {
    this.pane = new nicEditorPane(this.items,this.ne,{width : '108px', padding: '0px', borderTop : 0, borderLeft : '1px solid #ccc', borderRight : '1px solid #ccc', borderBottom : '0px', backgroundColor : '#fff'});

    for(var i=0;i<this.selOptions.length;i++) {
      var opt = this.selOptions[i];
      var itmContain = new bkElement('div').setStyle({overflow : 'hidden', borderBottom : '1px solid #ccc', width: '108px', textAlign : 'left', overflow : 'hidden', cursor : 'pointer'});
      var itm = new bkElement('div').setStyle({padding : '0px 4px'}).setContent(opt[1]).appendTo(itmContain).noSelect();
      itm.addEvent('click',this.update.closure(this,opt[0])).addEvent('mouseover',this.over.closure(this,itm)).addEvent('mouseout',this.out.closure(this,itm)).setAttributes('id',opt[0]);
      this.pane.append(itmContain);
      if(!window.opera) {
        itm.onmousedown = bkLib.cancelEvent;
      }
    }
  },

  close : function() {
    if(this.pane) {
      this.pane = this.pane.remove();
    }
  },

  over : function(opt) {
    opt.setStyle({backgroundColor : '#ccc'});
  },

  out : function(opt) {
    opt.setStyle({backgroundColor : '#fff'});
  },


  add : function(k,v) {
    this.selOptions.push(new Array(k,v));
  },

  update : function(elm) {
    this.ne.nicCommand(this.options.command,elm);
    this.close();
  }
});

var nicEditorFontSizeSelect = nicEditorSelect.extend({
  sel : {1 : '1&nbsp;(8pt)', 2 : '2&nbsp;(10pt)', 3 : '3&nbsp;(12pt)', 4 : '4&nbsp;(14pt)', 5 : '5&nbsp;(18pt)', 6 : '6&nbsp;(24pt)'},
  init : function() {
    this.setDisplay('Font&nbsp;Size...');
    for(itm in this.sel) {
      this.add(itm,'<font size="'+itm+'">'+this.sel[itm]+'</font>');
    }
  }
});

var nicEditorFontFamilySelect = nicEditorSelect.extend({
  sel : {'arial' : 'Arial','comic sans ms' : 'Comic Sans','courier new' : 'Courier New','georgia' : 'Georgia', 'helvetica' : 'Helvetica', 'impact' : 'Impact', 'times new roman' : 'Times', 'trebuchet ms' : 'Trebuchet', 'verdana' : 'Verdana'},

  init : function() {
    this.setDisplay('Font&nbsp;Family...');
    for(itm in this.sel) {
      this.add(itm,'<font face="'+itm+'">'+this.sel[itm]+'</font>');
    }
  }
});

var nicEditorFontFormatSelect = nicEditorSelect.extend({
  sel : {'p' : 'Paragraph', 'pre' : 'Pre', 'h6' : 'Heading&nbsp;6', 'h5' : 'Heading&nbsp;5', 'h4' : 'Heading&nbsp;4', 'h3' : 'Heading&nbsp;3', 'h2' : 'Heading&nbsp;2', 'h1' : 'Heading&nbsp;1'},

  init : function() {
    this.setDisplay('Font&nbsp;Format...');
    for(itm in this.sel) {
      var tag = itm.toUpperCase();
      this.add('<'+tag+'>','<'+itm+' style="padding: 0px; margin: 0px;">'+this.sel[itm]+'</'+tag+'>');
    }
  }
});

nicEditors.registerPlugin(nicPlugin,nicSelectOptions);



/* START CONFIG */
var nicLinkOptions = {
  buttons : {
    'link' : {name : 'Add Link', type : 'nicLinkButton', tags : ['A']},
    'unlink' : {name : 'Remove Link',  command : 'unlink', noActive : true}
  }
};
/* END CONFIG */

var nicLinkButton = nicEditorAdvancedButton.extend({
  addPane : function() {
    this.ln = this.ne.selectedInstance.selElm().parentTag('A');
    this.addForm({
      '' : {type : 'title', txt : 'Insert Link'},
      'title' : {type : 'text', txt : 'Link text'},
      'href' : {type : 'text', txt : 'URL', value : 'http://'},
      'target' : {type : 'select', txt : 'Open In', options : {'' : 'Current Window', '_blank' : 'New Window'} }
    },this.ln);
  },

  submit : function(e) {
    var url = this.inputs['href'].value;
    if(url == "http://" || url == "") {
      alert("You must enter a URL to Create a Link");
      return false;
    }
    this.removePane();

    if(!this.ln || !this.ln.setAttributes) {
      var tmp = this.inputs['title'].value;
      ( undefined === tmp || '' === tmp ) && ( tmp = 'new_link' ) ;
      this.ne.nicCommand("createlink",tmp);
      this.ln = this.findElm('A','href',tmp);
    }
    if(this.ln) {
      this.ln.setAttributes({
        href : this.inputs['href'].value,
        title : this.inputs['title'].value,
        target : this.inputs['target'].options[this.inputs['target'].selectedIndex].value
      });
    }
  }
});

nicEditors.registerPlugin(nicPlugin,nicLinkOptions);



/* START CONFIG */
var nicColorOptions = {
  buttons : {
    'forecolor' : {name : __('Change Text Color'), type : 'nicEditorColorButton', noClose : true},
    'bgcolor' : {name : __('Change Background Color'), type : 'nicEditorBgColorButton', noClose : true}
  }
};
/* END CONFIG */

var nicEditorColorButton = nicEditorAdvancedButton.extend({
  addPane : function() {
    var colorList = [
      ["#ffcaba", "#fda08c", "#fb7661", "#f8533b", "#f23a2c", "#e5342c", "#d73631", "#c22a32", "#9a0b2c"],
      ["#f6f4b7", "#f9f6a1", "#fee330", "#ffd200", "#fbb700", "#f6a300", "#f28a00", "#f27603", "#fb6e2c"],
      ["#d1e5c2", "#b5d994", "#97cb63", "#83bf47", "#72b235", "#5d9f27", "#4b8a21", "#39751d" ,"#2d681a"],
      ["#b5e0e1", "#9ad5d2", "#75c4be", "#54b2ae", "#2b9a9e", "#0c8691", "#026e7f", "#015268", "#064059"],
      ["#c4eeed", "#a9e7eb", "#8adfe9", "#6ed0e4", "#58b5da", "#4a95cf", "#3f72c1", "#3452b5", "#23399f"],
      ["#efdffd", "#cdbaf8", "#b099f0", "#9b7fe4", "#8d6dd2", "#7c5ac1", "#6344ad", "#4c309a", "#391f8a"],
      ["#fcc9dd", "#fca0c3", "#fc79ac", "#ee5398", "#e03c8f", "#cd2287", "#ad037c" ,"#7d0071", "#4c006a"],
      ["#ffffff", "#eeeeee", "#cdcdcd", "#959595" ,"#797979", "#636363", "#4f4f4f", "#3c3c3c", '#000000']
    ];
    var colorItems = new bkElement('DIV').setStyle({width: '270px'});

    for( var idx1 = 0, nMax1 = colorList.length; idx1 < nMax1; idx1++ ) {
      var colorRow = colorList[idx1];
      for( var idx2 = 0, nMax2 = colorRow.length; idx2 < nMax2; idx2++ ) {
        var colorCode = colorRow[idx2];
        var colorSquare = new bkElement('DIV').setStyle({'cursor' : 'pointer', padding:'2px 2px', 'height' : '15px', 'float' : 'left'}).appendTo(colorItems);
        var colorBorder = new bkElement('DIV').setStyle({border: '2px solid '+colorCode}).appendTo(colorSquare);
        var colorInner = new bkElement('DIV')
          .setStyle({backgroundColor : colorCode, overflow : 'hidden', width : '11px', height : '11px' })
          .addEvent('click',this.colorSelect.closure(this,colorCode))
          .addEvent('mouseover',this.on.closure(this,colorBorder))
          .addEvent('mouseout',this.off.closure(this,colorBorder,colorCode))
          .appendTo(colorBorder);
        if(!window.opera) {
          colorSquare.onmousedown = colorInner.onmousedown = bkLib.cancelEvent;
        }
      }
    }

    this.pane.append(colorItems.noSelect());
  },

  colorSelect : function(c) {
    this.ne.nicCommand('foreColor',c);
    this.removePane();
  },

  on : function(colorBorder) {
    colorBorder.setStyle({border : '2px solid #000'});
  },

  off : function(colorBorder,colorCode) {
    colorBorder.setStyle({border : '2px solid '+colorCode});
  }
});

var nicEditorBgColorButton = nicEditorColorButton.extend({
  colorSelect : function(c) {
    this.ne.nicCommand('hiliteColor',c);
    this.removePane();
  }
});

nicEditors.registerPlugin(nicPlugin,nicColorOptions);



/* START CONFIG */
var nicImageOptions = {
  buttons : {
    'image' : {name : 'Add Image', type : 'nicImageButton', tags : ['IMG']}
  }

};
/* END CONFIG */

var nicImageButton = nicEditorAdvancedButton.extend({
  addPane : function() {
    this.im = this.ne.selectedInstance.selElm().parentTag('IMG');
    this.addForm({
      '' : {type : 'title', txt : 'Add/Edit Image'},
      'src' : {type : 'text', txt : 'URL', 'value' : 'http://', style : {width: '150px'}},
      'alt' : {type : 'text', txt : 'Alt Text', style : {width: '100px'}},
      'align' : {type : 'select', txt : 'Align', options : {none : 'Default','left' : 'Left', 'right' : 'Right'}}
    },this.im);
  },

  submit : function(e) {
    var src = this.inputs['src'].value;
    if(src == "" || src == "http://") {
      alert("You must enter a Image URL to insert");
      return false;
    }
    this.removePane();

    if(!this.im) {
      var tmp = 'javascript:nicImTemp();';
      this.ne.nicCommand("insertImage",tmp);
      this.im = this.findElm('IMG','src',tmp);
    }
    if(this.im) {
      this.im.setAttributes({
        src : this.inputs['src'].value,
        alt : this.inputs['alt'].value,
        align : this.inputs['align'].value
      });
    }
  }
});

nicEditors.registerPlugin(nicPlugin,nicImageOptions);




/* START CONFIG */
var nicSaveOptions = {
  buttons : {
    'save' : {name : __('Save this content'), type : 'nicEditorSaveButton'}
  }
};
/* END CONFIG */

var nicEditorSaveButton = nicEditorButton.extend({
  init : function() {
    if(!this.ne.options.onSave) {
      this.margin.setStyle({'display' : 'none'});
    }
  },
  mouseClick : function() {
    var onSave = this.ne.options.onSave;
    var selectedInstance = this.ne.selectedInstance;
    onSave(selectedInstance.getContent(), selectedInstance.elm.id, selectedInstance);
  }
});

nicEditors.registerPlugin(nicPlugin,nicSaveOptions);



/* START CONFIG */
var nicUploadOptions = {
  buttons : {
    'upload' : {name : 'Upload Image', type : 'nicUploadButton'}
  }

};
/* END CONFIG */

var nicUploadButton = nicEditorAdvancedButton.extend({
  nicURI : 'https://api.imgur.com/3/image',
  errorText : 'Failed to upload image',

  addPane : function() {
    if(typeof window.FormData === "undefined") {
      return this.onError("Image uploads are not supported in this browser, use Chrome, Firefox, or Safari instead.");
    }
    this.im = this.ne.selectedInstance.selElm().parentTag('IMG');

    var container = new bkElement('div')
      .setStyle({ padding: '10px' })
      .appendTo(this.pane.pane);

    new bkElement('div')
      .setStyle({ fontSize: '14px', fontWeight : 'bold', paddingBottom: '5px' })
      .setContent('Insert an Image')
      .appendTo(container);

    this.fileInput = new bkElement('input')
      .setAttributes({ 'type' : 'file' })
      .appendTo(container);

    this.progress = new bkElement('progress')
      .setStyle({ width : '100%', display: 'none' })
      .setAttributes('max', 100)
      .appendTo(container);

    this.fileInput.onchange = this.uploadFile.closure(this);
  },

  onError : function(msg) {
    this.removePane();
    alert(msg || "Failed to upload image");
  },

  uploadFile : function() {
    var file = this.fileInput.files[0];
    if (!file || !file.type.match(/image.*/)) {
      this.onError("Only image files can be uploaded");
      return;
    }
    this.fileInput.setStyle({ display: 'none' });
    this.setProgress(0);

    var fd = new FormData(); // https://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/
    fd.append("image", file);

    var xhr = new XMLHttpRequest();
    xhr.open("POST", this.ne.options.uploadURI || this.nicURI);

    xhr.onload = function() {
      try {
        var data = JSON.parse(xhr.responseText).data;
      } catch(e) {
        return this.onError();
      }
      if(data.error) {
        return this.onError(data.error);
      }
      this.onUploaded(data);
    }.closure(this);
    xhr.onerror = this.onError.closure(this);
    xhr.upload.onprogress = function(e) {
      this.setProgress(e.loaded / e.total);
    }.closure(this);
    xhr.setRequestHeader('Authorization', 'Client-ID c37fc05199a05b7');
    xhr.send(fd);
  },

  setProgress : function(percent) {
    this.progress.setStyle({ display: 'block' });
    if(percent < .98) {
      this.progress.value = percent;
    } else {
      this.progress.removeAttribute('value');
    }
  },

  onUploaded : function(options) {
    this.removePane();
    var src = options.link;
    if(!this.im) {
      this.ne.selectedInstance.restoreRng();
      var tmp = 'javascript:nicImTemp();';
      this.ne.nicCommand("insertImage", src);
      this.im = this.findElm('IMG','src', src);
    }
    var w = parseInt(this.ne.selectedInstance.elm.getStyle('width'));
    if(this.im) {
      this.im.setAttributes({
        src : src,
        width : (w && options.width) ? Math.min(w, options.width) : ''
      });
    }
  }
});

nicEditors.registerPlugin(nicPlugin,nicUploadOptions);



var nicXHTML = bkClass.extend({
  stripAttributes : ['_moz_dirty','_moz_resizing','_extended'],
  noShort : ['style','title','script','textarea','a'],
  cssReplace : {'font-weight:bold;' : 'strong', 'font-style:italic;' : 'em'},
  sizes : {1 : 'xx-small', 2 : 'x-small', 3 : 'small', 4 : 'medium', 5 : 'large', 6 : 'x-large'},

  construct : function(nicEditor) {
    this.ne = nicEditor;
    if(this.ne.options.xhtml) {
      nicEditor.addEvent('get',this.cleanup.closure(this));
    }
  },

  cleanup : function(ni) {
    var node = ni.getElm();
    var xhtml = this.toXHTML(node);
    ni.content = xhtml;
  },

  toXHTML : function(n,r,d) {
    var txt = '';
    var attrTxt = '';
    var cssTxt = '';
    var nType = n.nodeType;
    var nName = n.nodeName.toLowerCase();
    var nChild = n.hasChildNodes && n.hasChildNodes();
    var extraNodes = new Array();

    switch(nType) {
      case 1:
        var nAttributes = n.attributes;

        switch(nName) {
          case 'b':
            nName = 'strong';
            break;
          case 'i':
            nName = 'em';
            break;
          case 'font':
            nName = 'span';
            break;
        }

        if(r) {
          for(var i=0;i<nAttributes.length;i++) {
            var attr = nAttributes[i];

            var attributeName = attr.nodeName.toLowerCase();
            var attributeValue = attr.nodeValue;

            if(!attr.specified || !attributeValue || bkLib.inArray(this.stripAttributes,attributeName) || typeof(attributeValue) == "function") {
              continue;
            }

            switch(attributeName) {
              case 'style':
                var css = attributeValue.replace(/ /g,"");
                for(itm in this.cssReplace) {
                  if(css.indexOf(itm) != -1) {
                    extraNodes.push(this.cssReplace[itm]);
                    css = css.replace(itm,'');
                  }
                }
                cssTxt += css;
                attributeValue = "";
                break;
              case 'class':
                attributeValue = attributeValue.replace("Apple-style-span","");
                break;
              case 'size':
                cssTxt += "font-size:"+this.sizes[attributeValue]+';';
                attributeValue = "";
                break;
            }

            if(attributeValue) {
              attrTxt += ' '+attributeName+'="'+attributeValue+'"';
            }
          }

          if(cssTxt) {
            attrTxt += ' style="'+cssTxt+'"';
          }

          for(var i=0;i<extraNodes.length;i++) {
            txt += '<'+extraNodes[i]+'>';
          }

          if(attrTxt == "" && nName == "span") {
            r = false;
          }
          if(r) {
            txt += '<'+nName;
            if(nName != 'br') {
              txt += attrTxt;
            }
          }
        }



        if(!nChild && !bkLib.inArray(this.noShort,attributeName)) {
          if(r) {
            txt += ' />';
          }
        } else {
          if(r) {
            txt += '>';
          }

          for(var i=0;i<n.childNodes.length;i++) {
            var results = this.toXHTML(n.childNodes[i],true,true);
            if(results) {
              txt += results;
            }
          }
        }

        if(r && nChild) {
          txt += '</'+nName+'>';
        }

        for(var i=0;i<extraNodes.length;i++) {
          txt += '</'+extraNodes[i]+'>';
        }

        break;
      case 3:
        //if(n.nodeValue != '\n') {
        txt += n.nodeValue;
        //}
        break;
    }

    return txt;
  }
});
nicEditors.registerPlugin(nicXHTML);



var nicBBCode = bkClass.extend({
  construct : function(nicEditor) {
    this.ne = nicEditor;
    if(this.ne.options.bbCode) {
      nicEditor.addEvent('get',this.bbGet.closure(this));
      nicEditor.addEvent('set',this.bbSet.closure(this));

      var loadedPlugins = this.ne.loadedPlugins;
      for(itm in loadedPlugins) {
        if(loadedPlugins[itm].toXHTML) {
          this.xhtml = loadedPlugins[itm];
        }
      }
    }
  },

  bbGet : function(ni) {
    var xhtml = this.xhtml.toXHTML(ni.getElm());
    ni.content = this.toBBCode(xhtml);
  },

  bbSet : function(ni) {
    ni.content = this.fromBBCode(ni.content);
  },

  toBBCode : function(xhtml) {
    function rp(r,m) {
      xhtml = xhtml.replace(r,m);
    }

    rp(/\n/gi,"");
    rp(/<strong>(.*?)<\/strong>/gi,"[b]$1[/b]");
    rp(/<em>(.*?)<\/em>/gi,"[i]$1[/i]");
    rp(/<span.*?style="text-decoration:underline;">(.*?)<\/span>/gi,"[u]$1[/u]");
    rp(/<ul>(.*?)<\/ul>/gi,"[list]$1[/list]");
    rp(/<li>(.*?)<\/li>/gi,"[*]$1[/*]");
    rp(/<ol>(.*?)<\/ol>/gi,"[list=1]$1[/list]");
    rp(/<img.*?src="(.*?)".*?>/gi,"[img]$1[/img]");
    rp(/<a.*?href="(.*?)".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
    rp(/<br.*?>/gi,"\n");
    rp(/<.*?>.*?<\/.*?>/gi,"");

    return xhtml;
  },

  fromBBCode : function(bbCode) {
    function rp(r,m) {
      bbCode = bbCode.replace(r,m);
    }

    rp(/\[b\](.*?)\[\/b\]/gi,"<strong>$1</strong>");
    rp(/\[i\](.*?)\[\/i\]/gi,"<em>$1</em>");
    rp(/\[u\](.*?)\[\/u\]/gi,"<span style=\"text-decoration:underline;\">$1</span>");
    rp(/\[list\](.*?)\[\/list\]/gi,"<ul>$1</ul>");
    rp(/\[list=1\](.*?)\[\/list\]/gi,"<ol>$1</ol>");
    rp(/\[\*\](.*?)\[\/\*\]/gi,"<li>$1</li>");
    rp(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");
    rp(/\[url=(.*?)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>");
    rp(/\n/gi,"<br />");
    //rp(/\[.*?\](.*?)\[\/.*?\]/gi,"$1");

    return bbCode;
  }


});
nicEditors.registerPlugin(nicBBCode);



nicEditor = nicEditor.extend({
  floatingPanel : function() {
    this.floating = new bkElement('DIV').setStyle({position: 'absolute', top : '-1000px'}).appendTo(document.body);
    this.addEvent('focus', this.reposition.closure(this)).addEvent('blur', this.hide.closure(this));
    this.setPanel(this.floating);
  },

  reposition : function() {
    var e = this.selectedInstance.e;
    this.floating.setStyle({ width : (parseInt(e.getStyle('width')) || e.clientWidth)+'px' });
    var top = e.offsetTop-this.floating.offsetHeight;
    if(top < 0) {
      top = e.offsetTop+e.offsetHeight;
    }

    this.floating.setStyle({ top : top+'px', left : e.offsetLeft+'px', display : 'block' });
  },

  hide : function() {
    this.floating.setStyle({ top : '-1000px'});
  }
});



/* START CONFIG */
var nicCodeOptions = {
  buttons : {
    'xhtml' : {name : 'Edit HTML', type : 'nicCodeButton'}
  }

};
/* END CONFIG */

var nicCodeButton = nicEditorAdvancedButton.extend({
  width : '350px',

  addPane : function() {
    this.addForm({
      '' : {type : 'title', txt : 'Edit HTML'},
      'code' : {type : 'content', 'value' : this.ne.selectedInstance.getContent(), style : {width: '340px', height : '200px'}}
    });
  },

  submit : function(e) {
    var code = this.inputs['code'].value;
    this.ne.selectedInstance.setContent(code);
    this.removePane();
  }
});

nicEditors.registerPlugin(nicPlugin,nicCodeOptions);


